package com.romotc.qqrobot.bean;

import java.sql.Timestamp;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;

import com.romotc.common.http.CookieUtil;
import com.romotc.joyin.bean.MemberCustService;
import com.romotc.json.tools.JsonObjectUtil;
import com.romotc.oschina.bean.POJO;
import com.romotc.qqrobot.exception.QQResInfoParseException;
import com.romotc.qqrobot.webqq.WebQQConstant;
import com.romotc.qqrobot.webqq.thread.GetMsgTipThread;
import com.romotc.qqrobot.webqq.thread.Poll2Thread;
import com.romotc.qqrobot.webqq.thread.SendMsgThread;
import com.romotc.scache.RequestSpy;

/**
 * 登入QQ的信息记录
 * @author Administrator
 *
 */
public class QQLogedin extends POJO implements Runnable{
	
	public QQLogedin(String uin, int clientId, String status, int cip,
			String vfwebqq, String psessionid, int user_state, int f, String cookieString) {
		this.uin = uin;
		this.clientId = clientId;
		this.status = status;
		this.cip = cip;
		this.vfwebqq = vfwebqq;
		this.psessionid = psessionid;
		this.user_state = user_state;
		this.f = f;
		this.cookieString = cookieString;
	}
	
	public QQLogedin()
	{
	}
	
	/**
	 * 放置QQ的一些属性，e.g:玫瑰小镇的玩家信息
	 */
	private Map<String, Object> qqProperties = new ConcurrentHashMap <String, Object>();
	public void  setProperties(String keyQqPropertiesPlayerinfo,
			Object data) {
		qqProperties.put(keyQqPropertiesPlayerinfo, data);
	}
	
	/**
	 * 获取QQ的属性
	 * @param key
	 * @return
	 */
	public Object getProperties(String key) {
		return qqProperties.get(key);
	}
	
	
	/*
	 * 本次登录的QQ号码
	 */
	private String uin;
	
	private int clientId;
	
	/**
	 * 登入时间
	 */
	private Timestamp loginTime = new Timestamp(System.currentTimeMillis());
	
	/**
	 * 在线状态
	 */
	private String status;
	
	private int cip;
	
	private String vfwebqq;
	
	private String psessionid;
	
	private int user_state;
	
	private int f;

	/**
	 * 获取本次信息的reqId
	 */
	private long reqId;
	/**
	 * 本次登录的Cookie串
	 */
	private String cookieString;
	
	
	
	/**
	 * 发送消息时的Msg_id
	 */
	private int msg_id;
	
	
	/**
	 * 接受消息时的msg_id 主要用用于 虚拟QQ
	 */
	private int reciveMsg_id;
	/**
	 * 自己的头像
	 */
	private int face;
	
	/**
	 * http://web.qq.com/web2/get_msg_tip?uin=&tp=1&id=0&retype=1&rc=11&lv=3&t=1326943639874
	 * 接口中rc递增
	 */
	private int rc;
	
	private String ptwebqq;
	
	/**
	 * 对应robotUser表id
	 */
	private long uid;

	private Thread taskThread;
	
	/**
	 * 在线滴答
	 */
	private GetMsgTipThread getMsgTipThread;
	private Poll2Thread poll2Thread;
	
	/**
	 * 发送消息线程
	 */
	private SendMsgThread sendMsgThread;
	
	
	/**
	 * 启动滴答线程
	 * @return 是否成功启动
	 */
	public boolean startKeepOnlineThread() {
		if(getMsgTipThread == null) {
			getMsgTipThread = new GetMsgTipThread(this.getUin());
			getMsgTipThread.start();
		}
		if(poll2Thread == null) {
			poll2Thread = new Poll2Thread(this.getUin());
			poll2Thread.start();
		}
		
		return true;
	}

	/**
	 * 停止滴答线程
	 */
	public void stopKeepOnlineThread() {
		if(getMsgTipThread != null) {
			getMsgTipThread.active = false;
			getMsgTipThread = null;
		}
		if(poll2Thread != null) {
			poll2Thread.active = false;
			poll2Thread = null;
		}
		
	}
	
	/**
	 * 是否为活动用户
	 */
	public boolean active = true;
	
	
	/**
	 * 所有使用本程序的QQ号码
	 */
	private static Map<String, QQLogedin> logedInNums = Collections.synchronizedMap(new HashMap<String, QQLogedin>());
	
	
	/**
	 * 获取当前登录的QQ号码信息
	 * @param qqNum
	 * @return
	 */
	public static QQLogedin getCurQqLogedIn(String qqNum) {
		if(StringUtils.isBlank(qqNum))
			return null;
		QQLogedin q =  logedInNums.get(qqNum);
		
		return q;
	}
	

	public static void removeQqLogedIn(String qqNum) {
		if(StringUtils.isBlank(qqNum))
			return;
		QQLogedin q =  logedInNums.remove(qqNum);
		
	}
	
	//线程终止计数器
	private int threadDown = 9;

	private long csId;

	/**
	 * 登录用户名
	 */
	private String loginUserName;
	
	public synchronized int modifyThreadDown(int chgSize) {
		if(threadDown > 9) {
			threadDown = 9;
			return 9;
		}
		
		threadDown = threadDown + chgSize;
		System.out.println(this.loginUserName + "-->" + threadDown);
		
		//临时代码
//		List<SendMsg> sendList = SendMsgService.qryMySendTask(this);
//		SendMsgService.sendMsg(sendList);
		
		return threadDown;
	}
	
	/**
	 * 一分钟运行的次数
	 */
	public static final int taskRunPreMin = 3;
	@Override
	/**
	 * 扫描当前QQ的任务 并执行
	 */
	public void run() {

		
		//先休眠1分钟 等待登录稳定下来
		try {
			Thread.sleep(60000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		boolean isRobot = WebQQConstant.isRobotUin(this.loginUserName);
		
		while(this.active && getCurQqLogedIn(this.loginUserName) != null) {
			if(!isRobot) {
				QQTaskService.runTask(this);
			}
			
			
			try {
				Thread.sleep(60000 / taskRunPreMin);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			//修改线程终止计数器
			modifyThreadDown(-1);//没有活动时3分钟就会被移除
			if(this.threadDown < 0 ) {
				if(!isRobot && this.getMsgTipThread == null 
						&& this.poll2Thread == null) {
					//普通QQ：启动滴答线程
					this.startKeepOnlineThread();
				}else if(isRobot){
					//虚拟QQ：移除
					removeQqLogedIn(this.loginUserName);
				}
			}

			//检查发送消息线程
			if(!isRobot)
			{
				//真实QQ号码需要启动发送消息扫描线程
				if(this.sendMsgThread == null) {
					this.sendMsgThread = new SendMsgThread(this.getLoginUserName());
					this.sendMsgThread.start();
				}
			}
			
		}
		
	}


	public static QQLogedin getCurQqLogedIn(RequestSpy rqSpy) {
		if(rqSpy == null || rqSpy.getReqCookiesJson() == null)
			return null;
		
		return getCurQqLogedIn(rqSpy.getReqCookiesJson().optString(WebQQConstant.Cookie_ptui_loginuin));
		
	}
	
	
	
	/**
	 * 从requestSpy构建QQLogedIn
	 * @param rqSpy
	 * @return
	 */
	public final static String LoginRetInfo_RetCode = "retcode";//正常登录返回 0
	public final static String LoginRetInfo_Result = "result";
	public static QQLogedin buildQQLogedIn(RequestSpy rqSpy) {
		String resBody = rqSpy.getResBody();
		try {
			JSONObject resInfo = new JSONObject(resBody);
			int loginRetcode = resInfo.getInt(LoginRetInfo_RetCode);
			if(loginRetcode == 0) {
				JSONObject loginInfo = resInfo.getJSONObject(LoginRetInfo_Result);
				int f = loginInfo.getInt("f");
				String statu = loginInfo.getString("status");
				String psessionid = loginInfo.getString("psessionid");
				String uin = loginInfo.getString("uin");
				int user_state = loginInfo.getInt("user_state");
				String vfwebqq = loginInfo.getString("vfwebqq"); 
				int cip = loginInfo.getInt("cip");
				
				JSONObject reqInfo = rqSpy.getReqInfoJson();
				String reqBody = reqInfo.getString("r");
				JSONObject reqBodyInfo = new JSONObject(reqBody);
				int clientid = reqBodyInfo.getInt("clientid");
				
				String cookieString = rqSpy.getReqCookiesStr();
				
				
				String loginUserName = rqSpy.getReqCookiesJson().optString(WebQQConstant.Cookie_ptui_loginuin, uin);
				
				QQLogedin qqLogedIn = getCurQqLogedIn(loginUserName);
				
				if(qqLogedIn == null) {
					qqLogedIn = new QQLogedin(uin, clientid, statu, cip,
							vfwebqq, psessionid, user_state, f, cookieString);
				}
				else if(qqLogedIn.active) {
					//活跃的 不需要生成直接可以使用
					qqLogedIn.stopKeepOnlineThread();
					return qqLogedIn;
				}
				else {//if 已经在登录数组中需要删除数据库中同id的 记录
					qqLogedIn.Delete();
				}

				
				
				qqLogedIn.setReqId(rqSpy.getReqSN());
				
				String ptwebqq = rqSpy.getReqCookiesJson().optString(WebQQConstant.Cookie_ptwebqq);
				qqLogedIn.setPtwebqq(ptwebqq);
				
				//这里uin 有三个可能的的含义：1.普通的QQ号 2.robotUser的supper subQQ 
				//3.虚拟工号的id根据cookie 登录账号格式判断
				
				boolean setUid = false;
				if(WebQQConstant.isRobotUin(loginUserName)) {
					//虚拟工号
					MemberCustService ms = MemberCustServiceService.qryMemberCustServiceById(Integer.valueOf(uin));
					if(ms != null) {
						qqLogedIn.setUid(ms.getUid());
						qqLogedIn.setCsId(ms.getId());//虚拟客服ID
						setUid = true;
					}
				}
/*				
				if(!setUid) {
					//查询sub_qq表 看看是否归属哪个robotUser
					RobotUserSubQq subQq = RobotUserSubQqService.qrySubQQ(uin);
					if(subQq != null)
						qqLogedIn.setUid(subQq.getUid());
					else {
						//没有则查找看之前是否使用过（robot_user）
						RobotUser user = RobotUserService.qryUser(uin);
						if(user == null) 
						{
							user = RobotUserService.createNewUser(uin);
						}
						qqLogedIn.setUid(user.getId());
						
					}
				}*/
				
				logedInNums.put(loginUserName, qqLogedIn);
				
				//启动任务扫描线程
/*				if(qqLogedIn.taskThread == null) {//如果之前没有启动过
					qqLogedIn.taskThread = new Thread(qqLogedIn);
					qqLogedIn.taskThread.start();
				}*/
				
				qqLogedIn.loginUserName = loginUserName;
//				qqLogedIn.Save();
				return qqLogedIn;
				
			}else {
				//登录失败需要记录下 romUndo
			}
		} catch (JSONException e) {
			//解析异常 说明有可能腾讯改了协议需要记录一下 romUnDo
			System.out.println(resBody);
			e.printStackTrace();
			throw new QQResInfoParseException(e);
		}
		return null;
	}
	
	
	private void setCsId(long csId) {
		this.csId = csId;
		
	}

	public String getUin() {
		return uin;
	}

	public void setUin(String uin) {
		this.uin = uin;
	}

	public int getClientId() {
		return clientId;
	}

	public void setClientId(int clientId) {
		this.clientId = clientId;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public int getCip() {
		return cip;
	}

	public void setCip(int cip) {
		this.cip = cip;
	}

	public String getVfwebqq() {
		return vfwebqq;
	}

	public void setVfwebqq(String vfwebqq) {
		this.vfwebqq = vfwebqq;
	}

	public String getPsessionid() {
		return psessionid;
	}

	public void setPsessionid(String psessionid) {
		this.psessionid = psessionid;
	}

	public int getUser_state() {
		return user_state;
	}

	public void setUser_state(int user_state) {
		this.user_state = user_state;
	}

	public int getF() {
		return f;
	}

	public void setF(int f) {
		this.f = f;
	}
	public String getCookieString() {
		return cookieString;
	}

	
	public void setCookieString(String cookieString) {
		this.cookieString = cookieString;
	}

	private JSONObject cookieObj;
	/**
	 * 获取Cookie值
	 * @param cookieName
	 * @return
	 */
	public String getCookieValue(String cookieName) {
		if(cookieObj == null)
			cookieObj = CookieUtil.parseCookieJsonFromStr(this.cookieString);
		return cookieObj.optString(cookieName);
	}

	public static void main(String args[]){
		
//		QQLogedin qqIn = new QQLogedin("97190865" , 1111, "online", 123, "vfwebqq" , "psessionid", 0, 0, "cookieStr");
//		System.out.println(qqIn.TableName());
//		qqIn.Save();
		
		
		
//		String string = "{\"status\":\"online\",\"ptwebqq\":\"76d631eea78d3e4884745c2318b2add340f64d396eeb7a3e9a2a11dd008be6b0\",\"passwd_sig\":\"\",\"clientid\":\"90521929\",\"psessionid\":null}";
//		try {
////			JSONObject sObject = new JSONObject(string);
////			System.out.println(sObject.get("ptwebqq"));
//			
//			QQLogedin qqLogedin = new QQLogedin();
//			System.out.println(qqLogedin.toString());
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		System.out.println("\u60A8\u7684\u8D26\u53F7\u5728\u53E6\u4E00\u5730\u70B9\u767B\u5F55\uFF0C\u60A8\u5DF2\u88AB\u8FEB\u4E0B\u7EBF\u3002\u5982\u6709\u7591\u95EE\uFF0C\u8BF7\u767B\u5F55 safe.qq.com \u4E86\u89E3\u66F4\u591A\u3002");
	}

	public Timestamp getLoginTime() {
		return loginTime;
	}

	public void setLoginTime(Timestamp loginTime) {
		this.loginTime = loginTime;
	}

	public long getReqId() {
		return reqId;
	}

	public void setReqId(long reqId) {
		this.reqId = reqId;
	}

	public synchronized int  getMsg_id() {
		return ++msg_id;
	}

	public synchronized void setMsg_id(int msg_id) {
		this.msg_id = msg_id;
	}

	public int getFace() {
		return face;
	}

	public void setFace(int face) {
		this.face = face;
	}

	public synchronized int getRc() {
		return ++rc;
	}

	public void setRc(int rc) {
		this.rc = rc;
	}

	public String getPtwebqq() {
		return ptwebqq;
	}

	public void setPtwebqq(String ptwebqq) {
		this.ptwebqq = ptwebqq;
	}

	@Override
	/**
	 * 返回腾讯的数据格式
	 */
	public String toString() {
		/**
		 * {"retcode":0,"result":{"uin":1586030808,"cip":1971856781,
				"index":1075,"port":45320,"status":"online",
				"vfwebqq":"71b58bfb568cec5e2346edff4b2a703171e8de0c178e9b3b0c24d9e948f39c94f28ba6e6492b5255",
				"psessionid":"8368046764001d636f6e6e7365727665725f77656271714031302e3133342e362e31333800004ea40000143c036e0400d8e8885e6d0000000a40616e6f7a7436685a776d0000002871b58bfb568cec5e2346edff4b2a703171e8de0c178e9b3b0c24d9e948f39c94f28ba6e6492b5255",
				"user_state":0,"f":0}}
		 */
		
		StringBuilder bld = new StringBuilder();
		bld.append("{\"retcode\":0,\"result\":{");
		
		bld.append("\"uin\":" + this.uin)
		.append(",\"cip\":").append(this.cip)
		.append(",\"index\":1075,\"port\":45320")
		.append(",\"status\":\"" + this.status).append("\"")
		.append(",\"vfwebqq\":\"").append(this.vfwebqq).append("\",")
		.append("\"psessionid\":\"").append(this.psessionid).append("\",")
		.append("\"user_state\":").append(this.user_state)
		.append(",\"f\":0");
		
		bld.append("}}");
		return bld.toString();
	}

	public long getUid() {
		return uid;
	}

	public void setUid(long uid) {
		this.uid = uid;
	}

	public long getCsId() {
		return csId;
	}

	public String getLoginUserName() {
		return loginUserName;
	}

	public void setLoginUserName(String loginUserName) {
		this.loginUserName = loginUserName;
	}

	public synchronized int getReciveMsg_id() {
		if(reciveMsg_id < 16000)
			reciveMsg_id = 16000;
		return reciveMsg_id++;
	}

	public synchronized void setReciveMsg_id(int reciveMsg_id) {
		this.reciveMsg_id = reciveMsg_id;
	}

	
}
